#include<iostream>
#include<string>
#include<algorithm>
#include<sstream>
#include<fstream>
#include<map>
#include<filesystem>
#include<vector>
#include<cctype>
#include<functional>
#include<unordered_set>

using namespace std::string_literals;
namespace fs = std::filesystem;
using fs::exists;
using fs::is_directory;
using fs::is_symlink;
using std::string;
using std::ifstream;
using std::cout;
using std::map;
using std::stringstream;
using std::vector;
using std::getline;
using std::remove_if;
using std::isspace;
using std::remove;
using std::find_if;
using std::find;
using std::bind;
using std::not_equal_to;
using std::placeholders::_1;
using std::all_of;
using std::logical_or;
using std::equal_to;
using std::make_pair;
using std::equal;
using std::count;
using std::adjacent_find;
using std::make_reverse_iterator;
using std::pair;
using std::isalnum;
using std::isspace;
using std::unordered_set;
using std::ofstream;


void test(const string &fileName,const string &output,const unordered_set<string> &testSet )
{
	if (fileName.empty() || output.empty() || testSet.empty())
		return;

	std::error_code err{};
	if (is_directory(fileName, err))
		return;
	if (err)
		return;
	bool onlyWord{ false }, checkSet{ false }, checkbrackets{ false };   //检查是否全部只是字母数字_   是否在set中  是否在函数体内
	vector<string>unknownVec, functionVec;
	vector<string>allVec;

	int noteLeft{}, noteRight{};
	string unknownStr,functionName;

	string::iterator iterBegin, iterEnd, iterNote,iterTempBegin,iterTempEnd;
	map<string, vector<string>>FunctionMap;
	string temp, checkTemp,checkStr;
	int index{};
	stringstream sstr;
	sstr << ifstream(fileName, std::ios::binary).rdbuf();
	while (!sstr.eof())
	{
		getline(sstr, temp);
		if (temp.empty())
			continue;
		if(checkStr.empty())
			allVec.emplace_back(temp);

		checkTemp.assign(temp);
		index = 0;
		iterNote = iterBegin = checkTemp.begin();
		while ((iterNote = adjacent_find(iterNote, checkTemp.end(), [](auto const left, auto const right)        //找到第一个注释的地方
		{
			return left == '/' && right == '/';
		})) != checkTemp.end())
		{
			while ((iterBegin = adjacent_find(iterBegin, iterNote, [](auto const left, auto const right)
			{
				return left != '\\' && right == '"';
			})) != iterNote)
			{
				++index;
				++iterBegin;
			}
			if (!(index % 2))
				break;
			++iterNote;
		}
		if ((iterEnd = iterNote) == checkTemp.begin())                   //表明整句话都是注释
			continue;
		if ((iterBegin = find_if(checkTemp.begin(), iterEnd, bind(not_equal_to<>(), _1, ' '))) == iterEnd)
			continue;
		iterEnd = find_if(make_reverse_iterator(iterEnd) + 1, make_reverse_iterator(iterBegin), bind(not_equal_to<>(), _1, ' ')).base();    //截取到注释之前不为空的字段

		index = 0;
		iterEnd = remove_if(iterBegin, iterEnd, [&index](const char ch)                             //去掉多余的空格  \r  \t
		{
			if (ch == '\r' || ch == '\t')return true;                            //   void   test            void test
			if (ch >= 0 && !isspace(ch))
			{
				index = 0;
				return false;
			}
			else
			{
				++index;
				return index > 1;
			}
		});
		checkTemp.assign(iterBegin, iterEnd);

		if (checkTemp.empty())
			continue;

		if (checkStr.empty())  //查找除了空格 大小写数字_以外的第一个字符  onlyWord表示全是空格 大小写数字_              handle_ffew435(
		{
			if ((iterTempBegin=find_if(checkTemp.begin(), checkTemp.end(), [](const char ch)
			{
				return ch<=0 || (ch>0 && !isalnum(ch) &&!isspace(ch)) && ch!='_';
			}))== checkTemp.end())
			{
				checkStr.assign(checkTemp);
				onlyWord = true;
				if(!allVec.empty())
					allVec.pop_back();
				unknownVec.emplace_back(temp);
				continue;
			}

			if (*iterTempBegin != '(')            //如果不是（退出   
			{
				continue;
			}

			functionName.assign(checkTemp.begin(), iterTempBegin);
			if (*(functionName.end() - 1) == ' ')
			{
				functionName.assign(functionName.begin(), find_if(functionName.rbegin(), functionName.rend(), bind(not_equal_to<>(), _1, ' ')).base());
			}

			if (testSet.find(functionName) == testSet.end())          
			{
				checkStr.clear();
				functionName.clear();
				continue;
			}
			checkSet = true;

			checkStr.assign(checkTemp);
			allVec.pop_back();
			unknownVec.emplace_back(temp);

			index = 0;
			iterTempEnd = iterTempBegin;
			while ((iterTempEnd = find(iterTempEnd, checkTemp.end(), ')')) != checkTemp.end())                // 查找有效的）  检查是否在""字符串中，暂未支持C++17的""s
			{
				while ((iterTempBegin = adjacent_find(iterTempBegin, iterTempEnd, [](const auto left, const auto right)
				{
					return left != '//' && right == '"';

				})) != iterTempEnd)
				{
					++index;
					++iterTempBegin;
				}
				if (!index || !(index % 2))
					break;
				++iterTempEnd;
			}

			if (iterTempEnd == checkTemp.end())
				continue;

			if ((iterTempBegin = find_if(iterTempEnd + 1, checkTemp.end(), bind(not_equal_to<>(), _1, ' '))) == checkTemp.end())
				continue;

			if (*iterTempBegin != '{')   //表明不是函数体           {}
			{
				functionName.clear();
				checkStr.clear();
				for (const auto &i : unknownVec)
					allVec.emplace_back(i);
				unknownVec.clear();
				continue;
			}
			checkbrackets = true;

			//这里开始表明是函数体
			functionVec.swap(unknownVec);

			noteLeft = noteRight = 0;             //分别统计{ 和 }的次数
			while ((iterTempBegin = find_if(iterTempBegin, checkTemp.end(), bind(logical_or<>(), bind(equal_to<>(), _1, '{'), bind(equal_to<>(), _1, '}')))) != checkTemp.end())
			{
				if (*iterTempBegin == '{')
					++noteLeft;
				else
					++noteRight;
				++iterTempBegin;
			}

			if (!noteLeft || noteLeft != noteRight)   //表明函数体没有结束
				continue;

			checkSet = checkbrackets = false;
			FunctionMap.insert(make_pair(functionName, functionVec));
			checkStr.clear();
			functionName.clear();
			functionVec.clear();

		}
		else
		{
			if (functionVec.empty())
				unknownVec.emplace_back(temp);
			else
				functionVec.emplace_back(temp);
			if (onlyWord )
				checkStr.append(string(1, ' '));
			checkStr.append(checkTemp);
			if (onlyWord)
			{
				if ((iterTempBegin = find_if(checkStr.begin(), checkStr.end(), [](const char ch)
				{
					return ch <= 0 || (ch > 0 && !isalnum(ch) && !isspace(ch)) && ch != '_';
				})) == checkStr.end())
				{
					continue;
				}

				onlyWord = false;
				if (*iterTempBegin != '(')            //如果不是（退出   
				{
					checkStr.clear();
					for (auto const &i : unknownVec)
						allVec.emplace_back(i);
					unknownVec.clear();
					continue;
				}

				functionName.assign(checkStr.begin(), iterTempBegin);                              //void test
				if (*(functionName.end() - 1) == ' ')
				{
					functionName.assign(functionName.begin(), find_if(functionName.rbegin(), functionName.rend(), bind(not_equal_to<>(), _1, ' ')).base());
				}
			}
			if (!checkSet)
			{
			if (testSet.find(functionName) == testSet.end())
			{
				checkStr.clear();
				functionName.clear();
				for (auto const &i : unknownVec)
					allVec.emplace_back(i);
				unknownVec.clear();
				continue;
			}

			checkSet = true;
			}
			if (!checkbrackets)
			{
				iterTempBegin = find_if(checkStr.begin(), checkStr.end(), [](const char ch)
				{
					return ch <= 0 || (ch > 0 && !isalnum(ch) && !isspace(ch) && ch != '_');
				});

				index = 0;
				iterTempEnd = iterTempBegin;
				while ((iterTempEnd = find(iterTempEnd, checkStr.end(), ')')) != checkStr.end())
				{
					while ((iterTempBegin = adjacent_find(iterTempBegin, iterTempEnd, [](const auto left, const auto right)
					{
						return left != '//' && right == '"';

					})) != iterTempEnd)
					{
						++index;
						++iterTempBegin;
					}
					if (!index || !(index % 2))
						break;
					++iterTempEnd;
				}

				if (iterTempEnd == checkStr.end())
					continue;

				if ((iterTempBegin = find_if(iterTempEnd + 1, checkStr.end(), bind(not_equal_to<>(), _1, ' '))) == checkStr.end())
					continue;

				if (*iterTempBegin != '{')   //表明不是函数体
				{
					functionName.clear();
					checkStr.clear();
					for (const auto &i : unknownVec)
						allVec.emplace_back(i);
					unknownVec.clear();
					continue;
				}
				checkbrackets = true;

				if (!unknownVec.empty())
				{
					for (auto const &i : unknownVec)
						functionVec.emplace_back(i);
					unknownVec.clear();
				}
				noteLeft = noteRight = 0;
				while ((iterTempBegin = find_if(iterTempBegin, checkStr.end()- checkTemp.size(), bind(logical_or<>(), bind(equal_to<>(), _1, '{'), bind(equal_to<>(), _1, '}')))) != (checkStr.end()- checkTemp.size()))
				{
					if (*iterTempBegin == '{')
						++noteLeft;
					else
						++noteRight;
					++iterTempBegin;
				}
				
			}
			iterTempBegin = checkTemp.begin();
			while ((iterTempBegin = find_if(iterTempBegin, checkTemp.end(), bind(logical_or<>(), bind(equal_to<>(), _1, '{'), bind(equal_to<>(), _1, '}')))) != checkTemp.end())
			{
				if (*iterTempBegin == '{')
					++noteLeft;
				else
					++noteRight;
				++iterTempBegin;
			}

			if (!noteLeft || noteLeft != noteRight)   //表明函数体没有结束
				continue;

			checkSet = checkbrackets = false;
			FunctionMap.insert(make_pair(functionName, functionVec));
			checkStr.clear();
			functionName.clear();
			functionVec.clear();
		}
	}

	if (int num = 1)
	{
		ofstream(output, std::ios::binary | std::ios::trunc) << "";
		sstr.str("");
		sstr.clear();
		for (auto const &i : allVec)
		{
			sstr << i;
		}
		for (auto const &i : testSet)
		{
			auto iter = FunctionMap.find(i);
			if (iter != FunctionMap.end())
			{
				for (auto const &j : iter->second)
					sstr << j ;
			}
		}
	}
	ofstream(output, std::ios::binary | std::ios::app) << sstr.str();
	cout << "Finish\n";
}

void checkConfig(const string &filename, unordered_set<string> &uset)
{
	if (!filename.empty())
	{
		if (!is_directory(filename) && exists(filename))
		{
			int index{};
			stringstream sstr;
			sstr << ifstream(filename, std::ios::binary).rdbuf();
			string str,temp;
			string::iterator iterBegin, iterEnd;
			while (!sstr.eof())
			{
				getline(sstr, str);
				if (!str.empty())
				{
					iterBegin = str.begin();
					index = 0;
					iterEnd = remove_if(iterBegin, str.end(), [&index](const char ch)                    //void test//
					{
						return ch=='\r';
						if (ch >= 0 && !isspace(ch))
						{
							index = 0;
							return false;
						}
						else
						{
							++index;
							return index > 1;
						}
					});

					if (iterEnd == iterBegin)
						continue;

					if ((iterBegin = find_if(iterBegin, iterEnd, bind(not_equal_to<>(), _1, ' '))) == iterEnd)
						continue;
					if ((iterEnd = find_if(make_reverse_iterator(iterEnd), make_reverse_iterator(iterBegin), bind(not_equal_to<>(), _1, ' ')).base()) == iterBegin)
						continue;
					temp.assign(iterBegin, iterEnd);
					uset.insert(temp);
				}
			}
		}
	}
}

int main()
{
	unordered_set<string>uset;
	checkConfig("G:/test/config.txt", uset);
	vector<string>testvec{ "G:/test/源24.cpp" };
	for (auto const &i : testvec)
	{
		test(i,"G:/test/output.txt", uset);
	}

	return 0;
}

//函数整理排列  
//比如一个cpp文件中有N个函数  我对这些函数的顺序要整理  比如原来的函数顺序是  A  N M。。。不规则的顺序 ， 我想解析之后按照自己想要的顺序去排列
//从配置文件中去获取你想要排列的函数顺序
